package com.yiyefanchen.ai.utils;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.data.domain.Sort;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {
    private final RedisTemplate<String, Object> redisTemplate;

    public RedisUtil(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    // ============================== Key 操作 ==============================

    /**
     * 获取所有符合指定表达式的 key
     * @param pattern 表达式
     * @return java.util.Set
     */
    public Set<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }

    /**
     * 删除属性
     * @param key key值
     * @return 返回成功
     */
    public Boolean del(String key) {
        return redisTemplate.delete(key);
    }

    /**
     * 批量删除属性
     * @param keys key值集合
     * @return 返回删除数量
     */
    public Long del(Collection<String> keys) {
        return redisTemplate.delete(keys);
    }

    /**
     * 设置过期时间
     * @param key key值
     * @param time 时间戳(秒)
     * @return 返回成功
     */
    public Boolean expire(String key, long time) {
        return redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    /**
     * 获取过期时间
     * @param key key值
     * @return 返回时间戳(秒)
     */
    public Long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     * @param key key值
     * @return 返回
     */
    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 检查键是否存在
     * @param key 键
     * @return 是否存在
     */
    public Boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 查看键的剩余生存时间
     * @param key 键
     * @return 剩余时间(秒)，-1表示永不过期，-2表示键不存在
     */
    public Long ttl(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 查看键的数据类型
     * @param key 键
     * @return 数据类型
     */
    public String type(String key) {
        return redisTemplate.type(key).code();
    }

    /**
     * 随机返回一个键
     * @return 随机键
     */
    public String randomKey() {
        return redisTemplate.randomKey();
    }

    /**
     * 重命名键
     * @param oldKey 旧键名
     * @param newKey 新键名
     */
    public void rename(String oldKey, String newKey) {
        redisTemplate.rename(oldKey, newKey);
    }

    /**
     * 仅当新键名不存在时重命名键
     * @param oldKey 旧键名
     * @param newKey 新键名
     * @return 是否重命名成功
     */
    public Boolean renameIfAbsent(String oldKey, String newKey) {
        return redisTemplate.renameIfAbsent(oldKey, newKey);
    }

    /**
     * 将当前数据库的键移动到指定数据库
     * @param key 键
     * @param dbIndex 目标数据库索引
     * @return 是否移动成功
     */
    public Boolean move(String key, int dbIndex) {
        return redisTemplate.move(key, dbIndex);
    }

    /**
     * 持久化键(移除过期时间)
     * @param key 键
     * @return 是否持久化成功
     */
    public Boolean persist(String key) {
        return redisTemplate.persist(key);
    }

    /**
     * 批量设置键值对
     * @param map 键值对集合
     */
    public void multiSet(Map<String, Object> map) {
        redisTemplate.opsForValue().multiSet(map);
    }

    /**
     * 当键不存在时设置键值对
     * @param key 键
     * @param value 值
     * @return 是否设置成功
     */
    public Boolean setIfAbsent(String key, Object value) {
        return redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    /**
     * 当键不存在时设置键值对并设置过期时间
     * @param key 键
     * @param value 值
     * @param time 过期时间(秒)
     * @return 是否设置成功
     */
    public Boolean setIfAbsent(String key, Object value, long time) {
        Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value);
        if (result != null && result) {
            expire(key, time);
        }
        return result;
    }

    // ============================== String 操作 ==============================

    /**
     * 保存属性
     * @param key key值
     * @param value value值
     * @param time 时间戳(秒)
     */
    public void set(String key, Object value, long time) {
        redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 保存属性
     * @param key key值
     * @param value value值
     */
    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 获取属性
     * @param key key值
     * @return 返回对象
     */
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 从指定的 keys 批量获取属性
     * @param keys keys
     * @return values list，当值为空时，该 key 对应的 value 为 null
     */
    public List<Object> mGet(Collection<String> keys) {
        return redisTemplate.opsForValue().multiGet(keys);
    }

    /**
     * 批量获取 keys 的属性，并返回一个 map
     * @param keys keys
     * @return map，key 和 value 的键值对集合，当 value 获取为 null 时，不存入此 map
     */
    public Map<String, Object> mGetToMap(Collection<String> keys) {
        List<Object> values = redisTemplate.opsForValue().multiGet(keys);
        Map<String, Object> map = new HashMap<>(keys.size());
        if (values == null || values.isEmpty()) {
            return map;
        }

        Iterator<String> keysIterator = keys.iterator();
        Iterator<Object> valuesIterator = values.iterator();
        while (keysIterator.hasNext()) {
            String key = keysIterator.next();
            Object value = valuesIterator.next();
            if (value != null) {
                map.put(key, value);
            }
        }
        return map;
    }

    /**
     * 按delta递增
     * @param key key值
     * @param delta delta值
     * @return 返回递增后结果
     */
    public Long incr(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 按delta递减
     * @param key key值
     * @param delta delta值
     * @return 返回递减后结果
     */
    public Long decr(String key, long delta) {
        return redisTemplate.opsForValue().decrement(key, delta);
    }

    /**
     * 获取字符串值的长度
     * @param key 键
     * @return 字符串长度
     */
    public Long strLen(String key) {
        return redisTemplate.opsForValue().size(key);
    }

    /**
     * 设置新值并返回旧值
     * @param key 键
     * @param value 新值
     * @return 旧值
     */
    public Object getAndSet(String key, Object value) {
        return redisTemplate.opsForValue().getAndSet(key, value);
    }

    /**
     * 对key所储存的字符串值，获取指定偏移量上的位(bit)
     * @param key 键
     * @param offset 偏移量
     * @return 位值
     */
    public Boolean getBit(String key, long offset) {
        return redisTemplate.opsForValue().getBit(key, offset);
    }

    /**
     * 对key所储存的字符串值，设置或清除指定偏移量上的位(bit)
     * @param key 键
     * @param offset 偏移量
     * @param value 位值
     * @return 原始位值
     */
    public Boolean setBit(String key, long offset, boolean value) {
        return redisTemplate.opsForValue().setBit(key, offset, value);
    }

    // ============================== Hash 操作 ==============================

    /**
     * 获取Hash结构中的属性
     * @param key 外部key值
     * @param hashKey 内部key值
     * @return 返回内部key的value
     */
    public Object hGet(String key, String hashKey) {
        return redisTemplate.opsForHash().get(key, hashKey);
    }

    /**
     * 向Hash结构中放入一个属性
     * @param key 外部key
     * @param hashKey 内部key
     * @param value 内部key的value
     * @param time 过期时间(秒)
     * @return 返回是否成功
     */
    public Boolean hSet(String key, String hashKey, Object value, long time) {
        redisTemplate.opsForHash().put(key, hashKey, value);
        return expire(key, time);
    }

    /**
     * 向Hash结构中放入一个属性
     * @param key 外部key
     * @param hashKey 内部key
     * @param value 内部key的value
     */
    public void hSet(String key, String hashKey, Object value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    /**
     * 直接获取整个Hash结构
     * @param key 外部key值
     * @return 返回hashMap
     */
    public Map<Object, Object> hGetAll(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 直接设置整个Hash结构
     * @param key 外部key
     * @param map hashMap值
     * @param time 过期时间(秒)
     * @return 返回是否成功
     */
    public Boolean hSetAll(String key, Map<String, Object> map, long time) {
        redisTemplate.opsForHash().putAll(key, map);
        return expire(key, time);
    }

    /**
     * 直接设置整个Hash结构
     * @param key 外部key
     * @param map hashMap值
     */
    public void hSetAll(String key, Map<String, ?> map) {
        redisTemplate.opsForHash().putAll(key, map);
    }

    /**
     * 删除Hash结构中的属性
     * @param key 外部key值
     * @param hashKey 内部key值
     */
    public void hDel(String key, Object... hashKey) {
        redisTemplate.opsForHash().delete(key, hashKey);
    }

    /**
     * 判断Hash结构中是否有该属性
     * @param key 外部key
     * @param hashKey 内部key
     * @return 返回是否存在
     */
    public Boolean hHasKey(String key, String hashKey) {
        return redisTemplate.opsForHash().hasKey(key, hashKey);
    }

    /**
     * Hash结构中属性递增
     * @param key 外部key
     * @param hashKey 内部key
     * @param delta 递增条件
     * @return 返回递增后的数据
     */
    public Long hIncr(String key, String hashKey, Long delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    /**
     * Hash结构中属性递减
     * @param key 外部key
     * @param hashKey 内部key
     * @param delta 递增条件
     * @return 返回递减后的数据
     */
    public Long hDecr(String key, String hashKey, Long delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, -delta);
    }

    // ============================== Set 操作 ==============================

    /**
     * 获取Set结构
     * @param key key
     * @return 返回set集合
     */
    public Set<Object> sMembers(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 向Set结构中添加属性
     * @param key key
     * @param values value集
     * @return 返回增加数量
     */
    public Long sAdd(String key, Object... values) {
        return redisTemplate.opsForSet().add(key, values);
    }

    /**
     * 向Set结构中添加属性
     * @param key key
     * @param time 过期时间(秒)
     * @param values 值集合
     * @return 返回添加的数量
     */
    public Long sAdd(String key, long time, Object... values) {
        Long count = redisTemplate.opsForSet().add(key, values);
        expire(key, time);
        return count;
    }

    /**
     * 是否为Set中的属性
     * @param key key
     * @param value value
     * @return 返回是否存在
     */
    public Boolean sIsMember(String key, Object value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * 获取Set结构的长度
     * @param key key
     * @return 返回长度
     */
    public Long sSize(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * 删除Set结构中的属性
     * @param key key
     * @param values value集合
     * @return 删除掉的数据量
     */
    public Long sRemove(String key, Object... values) {
        return redisTemplate.opsForSet().remove(key, values);
    }

    /**
     * 随机获取Set中的一个元素
     * @param key 键
     * @return 随机元素
     */
    public Object sRandomMember(String key) {
        return redisTemplate.opsForSet().randomMember(key);
    }

    /**
     * 随机获取Set中的多个元素
     * @param key 键
     * @param count 数量
     * @return 随机元素集合
     */
    public List<Object> sRandomMembers(String key, long count) {
        return redisTemplate.opsForSet().randomMembers(key, count);
    }

    /**
     * 将元素从源Set移动到目标Set
     * @param sourceKey 源键
     * @param value 值
     * @param destKey 目标键
     * @return 是否移动成功
     */
    public Boolean sMove(String sourceKey, Object value, String destKey) {
        return redisTemplate.opsForSet().move(sourceKey, value, destKey);
    }

    /**
     * 获取多个Set的差集
     * @param key 键
     * @param otherKey 其他键
     * @return 差集
     */
    public Set<Object> sDifference(String key, String otherKey) {
        return redisTemplate.opsForSet().difference(key, otherKey);
    }

    /**
     * 获取多个Set的差集并存储到新Set
     * @param key 新键
     * @param otherKey 其他键
     * @param thisKey 当前键
     * @return 差集大小
     */
    public Long sDifferenceAndStore(String key, String otherKey, String thisKey) {
        return redisTemplate.opsForSet().differenceAndStore(thisKey, otherKey, key);
    }


    // ============================== ZSet 操作 ==============================

    /**
     * 向ZSet中添加元素
     * @param key 键
     * @param value 值
     * @param score 分数
     * @return 是否添加成功
     */
    public Boolean zAdd(String key, Object value, double score) {
        return redisTemplate.opsForZSet().add(key, value, score);
    }

    /**
     * 向ZSet中添加多个元素
     * @param key 键
     * @param tuples 元素集合(值+分数)
     * @return 添加的数量
     */
    public Long zAdd(String key, Set<ZSetOperations.TypedTuple<Object>> tuples) {
        return redisTemplate.opsForZSet().add(key, tuples);
    }

    /**
     * 向ZSet中添加元素并设置过期时间
     * @param key 键
     * @param value 值
     * @param score 分数
     * @param time 过期时间(秒)
     * @return 是否添加成功
     */
    public Boolean zAdd(String key, Object value, double score, long time) {
        Boolean result = redisTemplate.opsForZSet().add(key, value, score);
        if (result) {
            expire(key, time);
        }
        return result;
    }

    /**
     * 获取ZSet中元素的分数
     * @param key 键
     * @param value 值
     * @return 分数
     */
    public Double zScore(String key, Object value) {
        return redisTemplate.opsForZSet().score(key, value);
    }

    /**
     * 获取ZSet中指定范围内的元素(按分数从小到大)
     * @param key 键
     * @param start 开始位置
     * @param end 结束位置
     * @return 元素集合
     */
    public Set<Object> zRange(String key, long start, long end) {
        return redisTemplate.opsForZSet().range(key, start, end);
    }

    /**
     * 获取ZSet中指定范围内的元素(按分数从大到小)
     * @param key 键
     * @param start 开始位置
     * @param end 结束位置
     * @return 元素集合
     */
    public Set<Object> zReverseRange(String key, long start, long end) {
        return redisTemplate.opsForZSet().reverseRange(key, start, end);
    }

    /**
     * 获取ZSet中指定分数范围的元素(按分数从小到大)
     * @param key 键
     * @param min 最小分数
     * @param max 最大分数
     * @return 元素集合
     */
    public Set<Object> zRangeByScore(String key, double min, double max) {
        return redisTemplate.opsForZSet().rangeByScore(key, min, max);
    }

    /**
     * 获取ZSet中指定分数范围的元素(带分数，按分数从小到大)
     * @param key 键
     * @param min 最小分数
     * @param max 最大分数
     * @return 元素和分数的集合
     */
    public Set<ZSetOperations.TypedTuple<Object>> zRangeByScoreWithScores(String key, double min, double max) {
        return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max);
    }

    /**
     * 获取ZSet中指定索引范围的元素(带分数，按分数从小到大)
     * @param key 键
     * @param start 开始索引
     * @param end 结束索引
     * @return 元素和分数的集合
     */
    public Set<ZSetOperations.TypedTuple<Object>> zRangeWithScores(String key, long start, long end) {
        return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
    }

    /**
     * 获取ZSet的大小
     * @param key 键
     * @return 元素数量
     */
    public Long zSize(String key) {
        return redisTemplate.opsForZSet().size(key);
    }

    /**
     * 获取ZSet中指定分数范围内的元素数量
     * @param key 键
     * @param min 最小分数
     * @param max 最大分数
     * @return 元素数量
     */
    public Long zCount(String key, double min, double max) {
        return redisTemplate.opsForZSet().count(key, min, max);
    }

    /**
     * 增加ZSet中元素的分数
     * @param key 键
     * @param value 值
     * @param delta 增加的分数
     * @return 增加后的分数
     */
    public Double zIncrementScore(String key, Object value, double delta) {
        return redisTemplate.opsForZSet().incrementScore(key, value, delta);
    }

    /**
     * 获取ZSet中元素的排名(按分数从小到大，从0开始)
     * @param key 键
     * @param value 值
     * @return 排名
     */
    public Long zRank(String key, Object value) {
        return redisTemplate.opsForZSet().rank(key, value);
    }

    /**
     * 获取ZSet中元素的排名(按分数从大到小，从0开始)
     * @param key 键
     * @param value 值
     * @return 排名
     */
    public Long zReverseRank(String key, Object value) {
        return redisTemplate.opsForZSet().reverseRank(key, value);
    }

    /**
     * 从ZSet中移除元素
     * @param key 键
     * @param values 值集合
     * @return 移除的数量
     */
    public Long zRemove(String key, Object... values) {
        return redisTemplate.opsForZSet().remove(key, values);
    }

    /**
     * 移除ZSet中指定排名范围的元素(按分数从小到大)
     * @param key 键
     * @param start 开始排名
     * @param end 结束排名
     * @return 移除的数量
     */
    public Long zRemoveRange(String key, long start, long end) {
        return redisTemplate.opsForZSet().removeRange(key, start, end);
    }

    /**
     * 移除ZSet中指定分数范围的元素
     * @param key 键
     * @param min 最小分数
     * @param max 最大分数
     * @return 移除的数量
     */
    public Long zRemoveRangeByScore(String key, double min, double max) {
        return redisTemplate.opsForZSet().removeRangeByScore(key, min, max);
    }

    /**
     * 获取两个ZSet的并集并存储到新的ZSet中
     * @param key 新的ZSet键
     * @param otherKey 另一个ZSet键
     * @param thisKey 当前ZSet键
     * @return 并集的大小
     */
    public Long zUnionAndStore(String key, String otherKey, String thisKey) {
        return redisTemplate.opsForZSet().unionAndStore(thisKey, otherKey, key);
    }

    /**
     * 获取多个ZSet的并集并存储到新的ZSet中
     * @param key 新的ZSet键
     * @param otherKeys 其他ZSet键集合
     * @param thisKey 当前ZSet键
     * @return 并集的大小
     */
    public Long zUnionAndStore(String key, Collection<String> otherKeys, String thisKey) {
        return redisTemplate.opsForZSet().unionAndStore(thisKey, otherKeys, key);
    }

    /**
     * 获取两个ZSet的交集并存储到新的ZSet中
     * @param key 新的ZSet键
     * @param otherKey 另一个ZSet键
     * @param thisKey 当前ZSet键
     * @return 交集的大小
     */
    public Long zIntersectAndStore(String key, String otherKey, String thisKey) {
        return redisTemplate.opsForZSet().intersectAndStore(thisKey, otherKey, key);
    }

    /**
     * 获取多个ZSet的交集并存储到新的ZSet中
     * @param key 新的ZSet键
     * @param otherKeys 其他ZSet键集合
     * @param thisKey 当前ZSet键
     * @return 交集的大小
     */
    public Long zIntersectAndStore(String key, Collection<String> otherKeys, String thisKey) {
        return redisTemplate.opsForZSet().intersectAndStore(thisKey, otherKeys, key);
    }


    // ============================== List 操作 ==============================

    /**
     * 获取List结构中的属性
     * @param key key
     * @param start 开始
     * @param end 结束
     * @return 返回查询的集合
     */
    public List<Object> lRange(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    /**
     * 获取List结构的长度
     * @param key key
     * @return 长度
     */
    public Long lSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    /**
     * 根据索引获取List中的属性
     * @param key key
     * @param index 索引
     * @return 对象
     */
    public Object lIndex(String key, long index) {
        return redisTemplate.opsForList().index(key, index);
    }

    /**
     * 向List结构中添加属性(右添加)
     * @param key key
     * @param value value
     * @return 增加后的长度
     */
    public Long lPush(String key, Object value) {
        return redisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * 向List结构中添加属性(右添加)
     * @param key key
     * @param value value
     * @param time 过期时间(秒)
     * @return 增加后的长度
     */
    public Long lPush(String key, Object value, long time) {
        Long index = redisTemplate.opsForList().rightPush(key, value);
        expire(key, time);
        return index;
    }

    /**
     * 向List结构中批量添加属性(右添加)
     * @param key key
     * @param values value 集合
     * @return 增加后的长度
     */
    public Long lPushAll(String key, Object... values) {
        return redisTemplate.opsForList().rightPushAll(key, values);
    }

    /**
     * 向List结构中批量添加属性(右添加)
     * @param key key
     * @param time 过期时间(秒)
     * @param values value集合
     * @return 增加后的长度
     */
    public Long lPushAll(String key, Long time, Object... values) {
        Long count = redisTemplate.opsForList().rightPushAll(key, values);
        expire(key, time);
        return count;
    }

    /**
     * 从List结构中移除属性
     * @param key key
     * @param count 总量
     * @param value value
     * @return 返回删除后的长度
     */
    public Long lRemove(String key, long count, Object value) {
        return redisTemplate.opsForList().remove(key, count, value);
    }

    /**
     * 从List左侧弹出元素
     * @param key 键
     * @return 弹出的元素
     */
    public Object lPop(String key) {
        return redisTemplate.opsForList().leftPop(key);
    }

    /**
     * 从List右侧弹出元素
     * @param key 键
     * @return 弹出的元素
     */
    public Object rPop(String key) {
        return redisTemplate.opsForList().rightPop(key);
    }

    /**
     * 从List左侧批量添加元素
     * @param key 键
     * @param values 值集合
     * @return 操作后列表长度
     */
    public Long lPushAllLeft(String key, Object... values) {
        return redisTemplate.opsForList().leftPushAll(key, values);
    }

    /**
     * 裁剪列表，只保留指定区间内的元素
     * @param key 键
     * @param start 开始索引
     * @param end 结束索引
     */
    public void lTrim(String key, long start, long end) {
        redisTemplate.opsForList().trim(key, start, end);
    }

    // ============================== BitMap 操作 ==============================

    /**
     * 向bitmap中新增值
     * @param key key
     * @param offset 偏移量
     * @param b 状态
     * @return 结果
     */
    public Boolean bitAdd(String key, int offset, boolean b) {
        return redisTemplate.opsForValue().setBit(key, offset, b);
    }

    /**
     * 从bitmap中获取偏移量的值
     * @param key key
     * @param offset 偏移量
     * @return 结果
     */
    public Boolean bitGet(String key, int offset) {
        return redisTemplate.opsForValue().getBit(key, offset);
    }

    /**
     * 获取bitmap的key值总和
     * @param key key
     * @return 总和
     */
    public Long bitCount(String key) {
        return redisTemplate.execute((RedisCallback<Long>) con -> con.bitCount(key.getBytes()));
    }

    /**
     * 获取bitmap范围值
     * @param key key
     * @param limit 范围
     * @param offset 开始偏移量
     * @return long类型集合
     */
    public List<Long> bitField(String key, int limit, int offset) {
        return redisTemplate.execute((RedisCallback<List<Long>>) con -> con.bitField(key.getBytes(),
                BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(limit)).valueAt(offset)));
    }

    /**
     * 获取所有bitmap
     * @param key key
     * @return 以二进制字节数组返回
     */
    public byte[] bitGetAll(String key) {
        return redisTemplate.execute((RedisCallback<byte[]>) con -> con.get(key.getBytes()));
    }

    // ============================== Geo 操作 ==============================

    /**
     * 增加坐标
     * @param key key
     * @param x x
     * @param y y
     * @param name 地点名称
     * @return 返回结果
     */
    public Long geoAdd(String key, Double x, Double y, String name) {
        return redisTemplate.opsForGeo().add(key, new Point(x, y), name);
    }

    /**
     * 根据城市名称获取坐标集合
     * @param key key
     * @param place 地点
     * @return 坐标集合
     */
    public List<Point> geoGetPointList(String key, Object... place) {
        return redisTemplate.opsForGeo().position(key, place);
    }

    /**
     * 计算两个城市之间的距离(单位:千米)
     * @param key key
     * @param placeOne 地点1
     * @param placeTow 地点2
     * @return 返回距离
     */
    public Distance geoCalculationDistance(String key, String placeOne, String placeTow) {
        return redisTemplate.opsForGeo().distance(key, placeOne, placeTow, RedisGeoCommands.DistanceUnit.KILOMETERS);
    }

    /**
     * 获取附该地点附近的其他地点
     * @param key key
     * @param place 地点
     * @param distance 附近的范围(单位:米)
     * @param limit 查几条
     * @param sort 排序规则
     * @return 返回附近的地点集合
     */
    public GeoResults<RedisGeoCommands.GeoLocation<Object>> geoNearByPlace(String key, String place, Distance distance,
                                                                           long limit, Sort.Direction sort) {
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                .includeDistance()
                .includeCoordinates();
        // 判断排序方式
        if (Sort.Direction.ASC == sort) {
            args.sortAscending();
        } else {
            args.sortDescending();
        }
        args.limit(limit);
        return redisTemplate.opsForGeo().radius(key, place, distance, args);
    }

    /**
     * 获取地点的hash
     * @param key key
     * @param place 地点
     * @return 返回集合
     */
    public List<String> geoGetHash(String key, String... place) {
        return redisTemplate.opsForGeo().hash(key, place);
    }

    // ============================== 锁操作 ==============================

    /**
     * 获取分布式锁
     * @param lockKey 锁键
     * @param value 值(通常为请求标识)
     * @param expireTime 过期时间(秒)
     * @return 是否获取成功
     */
    public Boolean tryLock(String lockKey, String value, long expireTime) {
        return redisTemplate.opsForValue().setIfAbsent(lockKey, value, expireTime, TimeUnit.SECONDS);
    }

    /**
     * 释放分布式锁
     * @param lockKey 锁键
     * @param value 值(必须与加锁时的值一致)
     * @return 是否释放成功
     */
    public Boolean releaseLock(String lockKey, String value) {
        String currentValue = (String) redisTemplate.opsForValue().get(lockKey);
        if (currentValue != null && currentValue.equals(value)) {
            return redisTemplate.delete(lockKey);
        }
        return false;
    }

    // ============================== 管道操作 ==============================

    /**
     * 执行管道操作
     * @param action 管道操作回调
     * @return 执行结果
     */
    public List<Object> executePipelined(RedisCallback<?> action) {
        return redisTemplate.executePipelined(action);
    }

// ============================== 事务操作 ==============================

    /**
     * 执行事务操作
     * @param action 事务操作回调
     * @return 执行结果
     */
    public Object executeTransaction(SessionCallback<?> action) {
        return redisTemplate.execute(action);
    }

    // ============================== Lua脚本执行 ==============================

    /**
     * 执行Lua脚本
     * @param script Lua脚本
     * @param keys 键集合
     * @param args 参数集合
     * @return 执行结果
     */
    public Object executeScript(String script, List<String> keys, Object... args) {
        RedisScript<Object> redisScript = new DefaultRedisScript<>(script, Object.class);
        return redisTemplate.execute(redisScript, keys, args);
    }

// ============================== HyperLogLog 操作 ==============================

    /**
     * 添加元素到HyperLogLog
     * @param key 键
     * @param values 值集合
     * @return 是否成功
     */
    public Long pfAdd(String key, Object... values) {
        return redisTemplate.opsForHyperLogLog().add(key, values);
    }

    /**
     * 获取HyperLogLog的基数估算值
     * @param key 键
     * @return 基数估算值
     */
    public Long pfCount(String key) {
        return redisTemplate.opsForHyperLogLog().size(key);
    }

    /**
     * 合并多个HyperLogLog到一个新的HyperLogLog
     * @param destKey 目标键
     * @param sourceKeys 源键集合
     * @return 是否成功
     */
    public Long pfMerge(String destKey, String... sourceKeys) {
        return redisTemplate.opsForHyperLogLog().union(destKey, sourceKeys);
    }



    // ============================== Stream 操作 ==============================

    /**
     * 添加消息到Stream
     * @param key 键
     * @param field 字段
     * @param value 值
     * @return 消息ID
     */
    public String streamAdd(String key, String field, Object value) {
        Map<String, Object> map = new HashMap<>();
        map.put(field, value);
        return redisTemplate.opsForStream().add(key, map).getValue();
    }

    

    // ============================== 高级功能 ==============================

    /**
     * 获取Redis连接工厂
     * @return Redis连接工厂
     */
    public RedisConnectionFactory getConnectionFactory() {
        return redisTemplate.getConnectionFactory();
    }

    /**
     * 获取原生RedisTemplate
     * @return RedisTemplate实例
     */
    public RedisTemplate<String, Object> getRedisTemplate() {
        return redisTemplate;
    }

    /**
     * 清空当前数据库
     */
    public void flushDb() {
        redisTemplate.execute((RedisCallback<Object>) connection -> {
            connection.flushDb();
            return null;
        });
    }

    /**
     * 清空所有数据库
     */
    public void flushAll() {
        redisTemplate.execute((RedisCallback<Object>) connection -> {
            connection.flushAll();
            return null;
        });
    }

    // ============================== 配置 ==============================

    /**
     * 创建 JSON 序列化器
     */
    public static RedisSerializer<Object> createRedisSerializer() {
        // 创建并配置ObjectMapper
        ObjectMapper objectMapper = new ObjectMapper()
                .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY)
                .activateDefaultTyping(
                        LaissezFaireSubTypeValidator.instance,
                        ObjectMapper.DefaultTyping.NON_FINAL
                );

        // 通过构造函数注入ObjectMapper（推荐方式）
        return new Jackson2JsonRedisSerializer<>(objectMapper, Object.class);
    }
}